
#ifndef _TTG_PIPELINE_TASK_KERNELS_
#define _TTG_PIPELINE_TASK_KERNELS_
#include "Common/Definitions.h"

#include "Common/Structures.h"
#include "Runtime.low/Threads.h"
#include "Runtime.Low/Services.h"

#include "IDataProcessor.h"
#include "../ContextMap.h"

namespace ttg_internal
{
	namespace pipeline
	{
		//Kernel, that invokes "process()" on CPU.
		template <class T>
		class ProcessKernel :public ttg::structures::InvokableObject
		{
			private:
				IDataProcessor<T> *processor;
				T _data;
				ttg::pipeline::ContextID context_id;
			public:
				//Creates ready-to-use kernel.
				inline ProcessKernel(IDataProcessor<T> *processor,
										T data,
										ttg::pipeline::ContextID context_id)
					:_data(data)
				{
					this->processor = processor;
					this->context_id = context_id;
				}
				//InvokableObject member.
				virtual void invoke()
				{
					processor->startProcessing(context_id);
					processor->process(context_id, _data);
					processor->finishProcessing(context_id);
				}
		};
		//Kernel for sub-pipeline finish handiling.
		template <class ProcessInType, class OutType>
		class CpuSubPipelineKernel :public ttg::structures::InvokableObject
		{
			private:
				IDataProcessor<ProcessInType> *processor;
				ttg::structures::Delegate<void, std::vector<OutType> &> *d;
				std::vector<OutType> *data;
				ttg::pipeline::ContextID context_id;
			public:
				//Creates ready-to-use kernel.
				//Note: "d" and "data" will be released by destructor.
				inline CpuSubPipelineKernel(IDataProcessor<ProcessInType> *processor,
											ttg::structures::Delegate<void, std::vector<OutType> &> *d,
											std::vector<OutType> *data,
											ttg::pipeline::ContextID context_id)
				{
					this->processor = processor;
					this->d = d;
					this->data = data;
					this->context_id = context_id;
				}
				//InvokableObject member.
				virtual void invoke()
				{
					processor->startProcessing(context_id);
					if (d != NULL)
					{ d->notify(*data); }
					processor->finishProcessing(context_id);
				}
				virtual ~CpuSubPipelineKernel()
				{
					SAFE_DELETE(d);
					SAFE_DELETE(data);
				}
		};
	}
}

#endif
